/*
 * mm-naive.c - The fastest, least memory-efficient malloc package.
 *
 * In this naive approach, a block is allocated by simply incrementing
 * the brk pointer.  A block is pure payload. There are no headers or
 * footers.  Blocks are never spacemerged or reused. Realloc is
 * implemented directly using mm_malloc and mm_free.
 *
 * NOTE TO STUDENTS: Replace this header comment with your own header
 * comment that gives a high level description of your solution.
 */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "mm.h"
#include "memlib.h"
/*********************************************************
 * NOTE TO STUDENTS: Before you do anything else, please
 * provide your team information in the following struct.
 ********************************************************/
team_t team = {
    /* Team name */
    "TJU",
    /* First member's full name */
    "Boyue Luan",
    /* First member's email address */
    "luanboyue@foxmail.com",
    /* Second member's full name (leave blank if none) */
    "",
    /* Second member's email address (leave blank if none) */
    ""};
// #define DEBUG
/* single word (4) or double word (8) alignment */
#define ALIGNMENT 8
/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~0x7) // 向上取整最近倍数
#define SIZE_T_SIZE (ALIGN(sizeof(size_t)))             // size_t的大小
static char *heap_listp;                                // 堆的起始指针
static char *Malloc_List_Beginner_ptr;                  // 空闲块链表的起始指针
#define ALLOCATED 1
#define FREE 0
#define WSIZE 4                              // 4bytes = 字
#define DSIZE 8                              // 8bytes = 双字
#define CHUNKSIZE 512                        /* 初始化堆大小 */
#define MAX(x, y) ((x) > (y) ? (x) : (y))    // 求最大值
#define MIN(x, y) ((x) < (y) ? (x) : (y))    // 求最小值
#define PACK(size, alloc) ((size) | (alloc)) // 将大小和分配位打包
/* 在 p 地址处读写一个字 */
#define GET(p) (*(unsigned int *)(p))                            // 读取一个字
#define WRITE(p, val) (*(unsigned int *)(p) = (unsigned int)val) // 写入一个字
/* 获得 block 的 Size 或 Alloc 信息 */
#define GET_SIZE(p) (GET(p) & ~0x7) // 获得块大小
#define GET_ALLOC(p) (GET(p) & 0x1) // 获得块分配信息
/* 获取 block 的 header 和 footer */
#define HEADERP(bptr) ((char *)(bptr) - WSIZE)                           // 获得块头部
#define FOOTERP(bptr) ((char *)(bptr) + GET_SIZE(HEADERP(bptr)) - DSIZE) // 获得块尾部
/* 获得给定block块的前驱或后继块 */
#define NEXT_BLKP(bptr) ((char *)(bptr) + GET_SIZE(HEADERP(bptr)))            // 获得下一个块
#define PREV_BLKP(bptr) ((char *)(bptr) - GET_SIZE(((char *)(bptr) - DSIZE))) // 获得前一个块
/* 获得当前\后继\前驱块大小 */
#define CRT_BLKSZ(bptr) GET_SIZE(HEADERP(bptr))             // 当前块大小
#define NEXT_BLKSZ(bptr) GET_SIZE(HEADERP(NEXT_BLKP(bptr))) // 下一个块大小
#define PREV_BLKSZ(bptr) GET_SIZE(HEADERP(PREV_BLKP(bptr))) // 前一个块大小
/* 块链表前驱后继 */
#define PREV(bptr) ((char *)(bptr) + WSIZE) // 前驱
#define SUFF(bptr) ((char *)bptr)           // 后继
/* 获取块链表前驱后继 */
#define PREF_BLKP(bptr) (GET(PREV(bptr))) // 获得块链表前驱
#define SUFF_BLKP(bptr) (GET(SUFF(bptr))) // 获得块链表后继
/* 大小类总类数 */
// 从2^4,2^5....类推
#define SEG_LEN 31
// #define DEBUG -1
static void Error_Handler(char *bp, char *__ERROR_MSG__);
static int get_index(size_t);
static size_t align_size(size_t);
static void *extend_heap(size_t);
static void *spacemerge(void *);
static void *find_fit(size_t, int);
static void *place(char *, size_t);

// Debug for Malloc
#ifdef DEBUG
static void print_funcname(char *name)
{
    printf("In %s\n", name);
}

/* print_heap_list: 打印堆块组织方式 */
static void print_heap_list(char *__FUNCNAME__)
{
    printf("-----------===  Block List ===--------------\n");
    print_funcname(__FUNCNAME__);
    char *bp = heap_listp;
    while (GET_ALLOC(HEADERP(bp)) != 1 || CRT_BLKSZ(bp) != 0)
    {
        if (!GET_ALLOC(HEADERP(bp)) && !CRT_BLKSZ(bp))
        {
            Error_Handler(bp, "RunTime Error: Heap Last Pointer Leak!!!\n");
            exit(-1);
        }
        printf("Block Pointer: %p \t Allocated: %d \t Size: %d\n", bp, GET_ALLOC(HEADERP(bp)), CRT_BLKSZ(bp));
        bp = NEXT_BLKP(bp);
    }
    printf("Block Pointer: %p \t Allocated: %d \t Size: %d\n", bp, GET_ALLOC(HEADERP(bp)), CRT_BLKSZ(bp));
    printf("----------------------------------------------------\n\n");
}

/* print_block_info: 打印bp指向块的详细信息 */
static void print_block_info(char *bp, char *__FUNCNAME__)
{
    printf("-------------=== BLOCK INFO ===----------------\n");
    print_funcname(__FUNCNAME__);
    printf("Pointer: %p\n", bp);
    char *__STATE__ = GET_ALLOC(HEADERP(bp)) == ALLOCATED ? "ALLOCATED" : "FREE";
    printf("STATE: %s \t Header_SIZE: %d \t Footer_SIZE: %d\n", __STATE__, GET_SIZE(HEADERP(bp)), GET_SIZE(FOOTERP(bp)));
    if (!GET_ALLOC(HEADERP(bp)))
    {
        int seg_index = get_index(CRT_BLKSZ(bp));
        char *root = Malloc_List_Beginner_ptr + seg_index * WSIZE;
        printf("ROOT: %p\n", root);
        if ((void *)PREV_BLKP(bp))
            printf("PREV_BLKP: %p \t", (void *)PREV_BLKP(bp));
        else
            printf("PREV_BLKP: NULL \t");
        if ((void *)SUFF_BLKP(bp))
            printf("SUsuff_BLKPC: %p \n", (void *)SUFF_BLKP(bp));
        else
            printf("SUFF_BLKP: NULL \n");
    }

    printf("----------------------------------------------------\n\n");
}

/* print_free_list: 打印当前空闲列表信息 */
static void print_free_list(char *__FUNCNAME__)
{
    printf("-------------=== FREE BLOCK LIST ===----------------\n");
    print_funcname(__FUNCNAME__);
    int seg_idx = 0;

    while (seg_idx < SEG_LEN)
    {
        char *root = Malloc_List_Beginner_ptr + seg_idx * WSIZE;
        char *bp = (char *)SUFF_BLKP(root);
        while (bp)
        {
            char *__STATE__ = GET_ALLOC(HEADERP(bp)) == ALLOCATED ? "ALLOCATED" : "FREE";
            printf("bp: %p \t ROOT: %p \t STATE: %s \t SIZE: %d \t", bp, root, __STATE__, CRT_BLKSZ(bp));

            if (!GET_ALLOC(HEADERP(bp)))
            {
                if ((void *)PREV_BLKP(bp))
                    printf("PREV_BLKP: %p \t", (void *)PREV_BLKP(bp));
                else
                    printf("PREV_BLKP: NULL \t");
                if ((void *)SUFF_BLKP(bp))
                    printf("SUFF_BLKP: %p \n\n", (void *)SUFF_BLKP(bp));
                else
                    printf("SUFF_BLKP: NULL \n\n");
            }
            bp = (char *)SUFF_BLKP(bp);
        }
        seg_idx++;
    }

    printf("----------------------------------------------------\n\n");
}

/* show_free_link: 展示以root开头的大小类空闲链表 */
static void show_free_link(char *root)
{
    if (SUFF_BLKP(root))
        printf("ROOT: %p --> ", root);
    else
    {
        printf("ROOT: %p\n", root);
        return;
    }
    char *suff = (char *)SUFF_BLKP(root);
    while (SUFF_BLKP(suff))
    {
        printf("%p ---> ", suff);
        suff = (char *)SUFF_BLKP(suff);
    }
    printf("%p\n", suff);
}
/* Error_Handler: 打印错误信息 */
static void Error_Handler(char *bp, char *__ERROR_MSG__)
{
    printf("%s", __ERROR_MSG__);
    print_block_info(bp, "Error");
}

/* mm_check: 进行全局检查 */
static void mm_check()
{
    char *cur_block;
    cur_block = heap_listp;

    // 直到结尾块结束
    while (CRT_BLKSZ(cur_block))
    {
        // 检查头尾是否一致
        if (GET_SIZE(HEADERP(cur_block)) != GET_SIZE(FOOTERP(cur_block)) ||
            GET_ALLOC(HEADERP(cur_block)) != GET_ALLOC(FOOTERP(cur_block)))
            Error_Handler(cur_block, "Runtime Error: Header and Footer Mismatch\n");
        // 检查合并
        if (!GET_ALLOC(HEADERP(cur_block)))
        {
            if (!GET_ALLOC(PREV_BLKP(cur_block)))
                Error_Handler(cur_block, "Runtime Error: PREV Coalescing Error\n");
            if (!GET_ALLOC(NEXT_BLKP(cur_block)))
                Error_Handler(cur_block, "Runtime Error: NEXT Coalescing Error\n");
        }
        cur_block = NEXT_BLKP(cur_block);
    }

    // 检查是否有已分配的块在空闲块链表里
    int seg_idx;
    for (seg_idx = 0; seg_idx < SEG_LEN; seg_idx++)
    {
        cur_block = Malloc_List_Beginner_ptr + seg_idx * WSIZE;
        while (cur_block)
        {
            if (GET_ALLOC(HEADERP(cur_block)))
                Error_Handler(cur_block, "Runtime Error: Allocated Block in Free List\n");
            cur_block = (char *)SUFF_BLKP(cur_block);
        }
    }
}

#endif
// 求log2
static int Log2(size_t x)
{
    int ans = 0;
    while (x >>= 1)
        ans++;
    return ans;
}
/*
 * get_index - 由大小获得大小类序号
 */
static int get_index(size_t v)
{
    int x = (int)Log2(v) - 4;
    if (x < 0)
        x = 0;
    if (x >= SEG_LEN)
        x = SEG_LEN - 1;
    return x;
}

/*
 * insert_free_block - 插入块
 */
static void insert_free_block(char *freebptr)
{
    // 获得插入块所属大小类
    // 使用CRT_BLKSZ(freebptr)获取块的大小，然后使用get_index函数获取对应的大小类索引
    int index = get_index(CRT_BLKSZ(freebptr));
    // 计算全局列表的起始地址，每个大小类的起始地址是global_list_start_ptr + index * WSIZE
    char *root = Malloc_List_Beginner_ptr + index * WSIZE;

    // 地址排序 - Address Order
    // 初始化suff为当前大小类的根节点
    void *suff = root;

    // 遍历当前大小类的所有块

    while (SUFF_BLKP(suff))
    {
        // 更新suff为其后继块
        suff = (char *)SUFF_BLKP(suff);
        // 如果suff的地址大于等于待插入块的地址
        if ((unsigned int)suff >= (unsigned int)freebptr)
        {
            // 安装地址顺序插入空闲块
            // PREF_BLKP(suff) <-> freebptr <-> suff
            // 保存suff的值
            char *tmp = suff;
            // 更新suff为其前驱块
            suff = (char *)PREF_BLKP(suff);
            // 将fbp插入到suff和tmp之间
            WRITE(SUFF(suff), freebptr);
            WRITE(PREV(freebptr), suff);
            WRITE(SUFF(freebptr), tmp);
            WRITE(PREV(tmp), freebptr);

            // 插入完成后返回
            return;
        }
    }

    // Base Case & Last Case
    // 当前大小类没有空闲块，或者在地址分配时，当前空闲块地址最大被分配在最后
    // 将fbp插入到链表的最后
    WRITE(SUFF(suff), freebptr);
    // 将fbp的前驱指针设置为suff
    WRITE(PREV(freebptr), suff);
    // 将fbp的后继指针设置为NULL，表示fbp是链表的最后一个元素
    WRITE(SUFF(freebptr), NULL);
}

/*
 * delete_free_block - 删除块
 */
static void delete_free_block(char *freebptr)
{
    // 获取空闲块所属的大小类索引
    int index = get_index(CRT_BLKSZ(freebptr));
    // 计算全局列表的起始地址
    char *root = Malloc_List_Beginner_ptr + index * WSIZE;

    // 正常情况：空闲块有前驱块和后继块
    if (SUFF_BLKP(freebptr) && PREF_BLKP(freebptr))
    {
        // 将前驱块的后继指针指向当前块的后继块
        WRITE(SUFF(PREF_BLKP(freebptr)), SUFF_BLKP(freebptr));
        // 将后继块的前驱指针指向当前块的前驱块
        WRITE(PREV(SUFF_BLKP(freebptr)), PREF_BLKP(freebptr));
    }
    else if (PREF_BLKP(freebptr))
    { // 最后一个块的情况
        // 将前驱块的后继指针设置为NULL
        WRITE(SUFF(PREF_BLKP(freebptr)), NULL);
    }

    // 将当前块的后继指针和前驱指针都设置为NULL
    WRITE(SUFF(freebptr), NULL);
    WRITE(PREV(freebptr), NULL);
}
/*
 * mm_init - 初始化
 */
int mm_init(void)
{
    // 使用mem_sbrk函数分配内存，如果分配失败，返回-1
    if ((heap_listp = mem_sbrk((SEG_LEN + 3) * WSIZE)) == (void *)-1)
        return -1;
    int i;

    // 初始化空闲块大小类头指针
    for (i = 0; i < SEG_LEN; ++i)
        WRITE(heap_listp + i * WSIZE, NULL);

    // 初始化序言块和结尾块
    WRITE(heap_listp + (i + 0) * WSIZE, PACK(DSIZE, ALLOCATED)); /* 序言块头部 */
    WRITE(heap_listp + (i + 1) * WSIZE, PACK(DSIZE, ALLOCATED)); /* 序言块尾部 */
    WRITE(heap_listp + (i + 2) * WSIZE, PACK(0, ALLOCATED));     /* 结尾块头部 */

    // 设置全局列表的起始指针
    Malloc_List_Beginner_ptr = heap_listp;
    // 对齐到起始块有效载荷
    heap_listp += (i + 1) * WSIZE;

    // 扩展空栈至 CHUNKSIZE bytes，如果扩展失败，返回-1
    if (extend_heap(CHUNKSIZE) == NULL)
        return -1;
    return 0;
}
/*
 * mm_malloc - 分配块，首次适配 & 立即合并策略
 */
void *mm_malloc(size_t size)
{
    // 调整后的块大小
    size_t asize = align_size(size);
    // 扩展堆大小
    size_t extendsize;
    char *bptr;

    // Trivial Case
    // 如果请求的大小为0，直接返回NULL
    if (size == 0)
        return NULL;

    // 寻找适配
    // 使用find_fit函数寻找大小为asize的空闲块
    // 如果找到了合适的空闲块，使用place函数将其分配给用户
    if ((bptr = find_fit(asize, get_index(asize))) != NULL)
        return place(bptr, asize);

    // 未找到适配，分配更多堆空间
    // 如果没有找到合适的空闲块，那么需要扩展堆空间
    // 扩展的大小是asize和CHUNKSIZE中的较大者
    extendsize = MAX(asize, CHUNKSIZE);
    // 使用extend_heap函数扩展堆空间
    // 如果扩展失败，返回NULL
    if ((bptr = extend_heap(extendsize)) == NULL)
        return NULL;

    // 使用place函数将新扩展的堆空间分配给用户
    return place(bptr, asize);
}
/*
 * mm_free - 释放块并立即合并
 */
void mm_free(void *ptr)
{
    // 获取要释放的块的指针
    char *bptr = ptr;
    // 获取块的大小
    size_t size = CRT_BLKSZ(bptr);
    // 将块的头部和尾部都标记为空闲
    WRITE(HEADERP(bptr), PACK(size, FREE));
    WRITE(FOOTERP(bptr), PACK(size, FREE));
    // 合并相邻的空闲块
    spacemerge(bptr);
}
/*
 * mm_realloc - 重新分配
 */
void *mm_realloc(void *ptr, size_t size)
{
    // 如果 ptr == NULL 直接分配
    // 如果传入的指针为空，则直接调用mm_malloc函数进行分配
    if (ptr == NULL)
        return mm_malloc(size);
    // 如果 size == 0 就释放
    // 如果传入的大小为0，则释放该指针，并返回NULL
    else if (size == 0)
    {
        mm_free(ptr);
        return NULL;
    }

    // 调整后的块大小和旧块大小
    size_t asize = align_size(size), old_size = CRT_BLKSZ(ptr);
    // 计算移动的大小，取asize和old_size中的较小者
    size_t mv_size = MIN(asize, old_size);
    char *oldptr = ptr;
    char *newptr;

    // 如果旧块大小等于调整后的块大小，直接返回原指针
    if (old_size == asize)
        return ptr;

    // 获取前一个块和后一个块的分配状态
    size_t prev_alloc = GET_ALLOC(FOOTERP(PREV_BLKP(ptr)));
    size_t next_alloc = GET_ALLOC(HEADERP(NEXT_BLKP(ptr)));
    // 获取后一个块的大小
    size_t next_size = NEXT_BLKSZ(ptr);
    char *next_bp = NEXT_BLKP(ptr);
    size_t total_size = old_size;

    // 后面的块是空闲的，并且旧块和后面的空闲块的总大小大于等于调整后的块大小
    if (prev_alloc && !next_alloc && (old_size + next_size >= asize))
    {
        // 删除后面的空闲块，并将其合并到旧块中
        total_size += next_size;
        delete_free_block(next_bp);
        WRITE(HEADERP(ptr), PACK(total_size, ALLOCATED));
        WRITE(FOOTERP(ptr), PACK(total_size, ALLOCATED));
        place(ptr, total_size);
    }
    // 后面没有块，并且调整后的块大小大于等于旧块大小
    else if (!next_size && asize >= old_size)
    {
        // 扩展旧块的大小
        size_t extend_size = asize - old_size;
        if ((long)(mem_sbrk(extend_size)) == -1)
            return NULL;

        WRITE(HEADERP(ptr), PACK(total_size + extend_size, ALLOCATED));
        WRITE(FOOTERP(ptr), PACK(total_size + extend_size, ALLOCATED));
        WRITE(HEADERP(NEXT_BLKP(ptr)), PACK(0, ALLOCATED));
        place(ptr, asize);
    }
    // 其他情况
    else
    {
        // 分配一个新的块，并将旧块的内容复制到新块中，然后释放旧块
        newptr = mm_malloc(asize);
        if (newptr == NULL)
            return NULL;
        memcpy(newptr, ptr, MIN(old_size, size));
        mm_free(ptr);
        return newptr;
    }

    return ptr;
}
/*
 * extend_heap - 扩展堆，对齐size，并执行合并，返回bp指针
 */
static void *extend_heap(size_t asize)
{
    char *bptr;
    if ((long)(bptr = mem_sbrk(asize)) == -1)
    {
        // Alloc Error
        return NULL;
    }
    /* 初始化空闲块的头尾和结尾块的头部 */
    WRITE(HEADERP(bptr), PACK(asize, FREE));             /* 空闲块头部 */
    WRITE(FOOTERP(bptr), PACK(asize, FREE));             /* 空闲块尾部 */
    WRITE(HEADERP(NEXT_BLKP(bptr)), PACK(0, ALLOCATED)); /* 结尾块头部 */
    return spacemerge(bptr);
}
/*
 * spacemerge - 对bp指向块进行前后合并，返回bp指针
 */
static void *spacemerge(void *bptr)
{
    // 获取前一个块和后一个块的分配状态
    size_t prev_alloc = GET_ALLOC(FOOTERP(PREV_BLKP(bptr)));
    size_t next_alloc = GET_ALLOC(HEADERP(NEXT_BLKP(bptr)));
    // 获取当前块的大小
    size_t size = CRT_BLKSZ(bptr);

    // 前后块都非空闲
    if (prev_alloc && next_alloc)
    {
        // 将当前块插入到空闲块列表中
        insert_free_block(bptr);
        return bptr;
    }
    // 后块空闲
    else if (prev_alloc && !next_alloc)
    {
        // 更新当前块的大小，包括后一个空闲块的大小
        size += NEXT_BLKSZ(bptr);
        // 从空闲块列表中删除后一个块
        delete_free_block(NEXT_BLKP(bptr));
        // 更新当前块的头部和尾部，标记为空闲
        WRITE(HEADERP(bptr), PACK(size, FREE));
        WRITE(FOOTERP(bptr), PACK(size, FREE));
        // 清空当前块的前驱和后继指针
        WRITE(PREV(bptr), NULL);
        WRITE(SUFF(bptr), NULL);
    }
    // 前块空闲
    else if (!prev_alloc && next_alloc)
    {
        // 更新当前块的大小，包括前一个空闲块的大小
        size += PREV_BLKSZ(bptr);
        // 从空闲块列表中删除前一个块
        delete_free_block(PREV_BLKP(bptr));
        // 更新当前块的头部和尾部，标记为空闲
        WRITE(FOOTERP(bptr), PACK(size, FREE));
        WRITE(HEADERP(PREV_BLKP(bptr)), PACK(size, FREE));
        // 更新当前块的指针，指向前一个块
        bptr = PREV_BLKP(bptr);
        // 清空当前块的前驱和后继指针
        WRITE(PREV(bptr), NULL);
        WRITE(SUFF(bptr), NULL);
    }
    // 前后块都空闲
    else
    {
        // 更新当前块的大小，包括前后两个空闲块的大小
        size += NEXT_BLKSZ(bptr) + PREV_BLKSZ(bptr);
        // 从空闲块列表中删除前后两个块
        delete_free_block(PREV_BLKP(bptr));
        delete_free_block(NEXT_BLKP(bptr));
        // 更新当前块的头部和尾部，标记为空闲
        WRITE(HEADERP(PREV_BLKP(bptr)), PACK(size, FREE));
        WRITE(FOOTERP(NEXT_BLKP(bptr)), PACK(size, FREE));
        // 更新当前块的指针，指向前一个块
        bptr = PREV_BLKP(bptr);
        // 清空当前块的前驱和后继指针
        WRITE(PREV(bptr), NULL);
        WRITE(SUFF(bptr), NULL);
    }
    // 将当前块插入到空闲块列表中
    insert_free_block(bptr);
    return bptr;
}
/*
 * align_size - 对块大小进行对齐，留出首尾空间，返回真实分配大小
 */
static size_t align_size(size_t size)
{
    /* 调整块大小 */
    // 如果请求的大小小于等于DSIZE（双字大小），则返回2 * DSIZE，这是最小的块大小
    if (size <= DSIZE)
        return 2 * DSIZE;
    // 否则，将请求的大小调整为DSIZE的倍数
    // 这是通过将请求的大小加上DSIZE和DSIZE-1，然后除以DSIZE，再乘以DSIZE来实现的
    // 这样可以确保返回的大小总是DSIZE的倍数
    return DSIZE * ((size + (DSIZE) + (DSIZE - 1)) / DSIZE);
}
/*
 * find_fit - 寻找适配，返回适配到的空闲块指针,使用首次适配
 */
static void *find_fit(size_t size, int seg_idx)
{
    // 首次适应算法
    char *res;
    // 遍历所有的分段，从给定的分段索引开始
    while (seg_idx < SEG_LEN)
    {
        // 获取当前分段的根节点
        char *root = Malloc_List_Beginner_ptr + seg_idx * WSIZE;
        // 获取当前分段的第一个块
        char *bptr = (char *)SUFF_BLKP(root);
        // 遍历当前分段的所有块
        while (bptr)
        {
            // 如果当前块的大小大于等于请求的大小，则返回当前块
            if ((size_t)CRT_BLKSZ(bptr) >= size)
                return bptr;

            // 移动到下一个块
            bptr = (char *)SUFF_BLKP(bptr);
        }
        // 如果在当前分段中没有找到合适的块，则移动到下一个分段
        seg_idx++;
    }
    // 如果在所有分段中都没有找到合适的块，则返回NULL
    return NULL;
}
/*
 * place - 放置块，若剩余后部大于一个最小块大小(16 bytes)就进行分割
 */
static void *place(char *bptr, size_t asize)
{
    // 获取当前块的大小
    size_t blk_size = CRT_BLKSZ(bptr);
    // 计算剩余的大小（当前块的大小减去请求的大小）
    size_t rm_size = blk_size - asize;

    // 如果当前块是空闲的，则从空闲块列表中删除
    if (!GET_ALLOC(HEADERP(bptr)))
        delete_free_block(bptr);

    // 如果剩余的大小大于等于2 * DSIZE（最小的块大小）
    if (rm_size >= 2 * DSIZE)
    {
        // 如果请求的大小大于64
        if (asize > 64)
        {
            // 将当前块分割为两个块，前一个块的大小为剩余的大小，后一个块的大小为请求的大小
            // 并将前一个块标记为空闲，后一个块标记为已分配
            WRITE(HEADERP(bptr), PACK(rm_size, FREE));
            WRITE(FOOTERP(bptr), PACK(rm_size, FREE));
            WRITE(HEADERP(NEXT_BLKP(bptr)), PACK(asize, ALLOCATED));
            WRITE(FOOTERP(NEXT_BLKP(bptr)), PACK(asize, ALLOCATED));
            // 将前一个块插入到空闲块列表中
            insert_free_block(bptr);
            // 返回后一个块
            return NEXT_BLKP(bptr);
        }
        else
        {
            // 将当前块分割为两个块，前一个块的大小为请求的大小，后一个块的大小为剩余的大小
            // 并将前一个块标记为已分配，后一个块标记为空闲
            WRITE(HEADERP(bptr), PACK(asize, ALLOCATED));
            WRITE(FOOTERP(bptr), PACK(asize, ALLOCATED));
            WRITE(HEADERP(NEXT_BLKP(bptr)), PACK(rm_size, FREE));
            WRITE(FOOTERP(NEXT_BLKP(bptr)), PACK(rm_size, FREE));
            // 将后一个块与其相邻的空闲块合并
            spacemerge(NEXT_BLKP(bptr));
        }
    }
    else
    {
        // 如果剩余的大小小于2 * DSIZE，则将整个块分配出去
        // 并将块标记为已分配
        WRITE(HEADERP(bptr), PACK(blk_size, ALLOCATED));
        WRITE(FOOTERP(bptr), PACK(blk_size, ALLOCATED));
    }
    // 返回当前块
    return bptr;
}
